//
//  RxSwiftExample.swift
//  SwiftCode
//
//  Created by yuhus on 2023/6/27.
//

import UIKit
import RxSwift

class RxSwiftExample: ListViewController {
  override func getItemCount() -> Int {
    data.count
  }
  
  override func getItem(_ indexPath: IndexPath) -> Item {
    data[indexPath.row]
  }
  
  private lazy var data: [Item] = [
    .init(title: "do", description: "操作符 do", action: doRx),
    .init(title: "concat", description: "操作符 concat", action: concatRx),
    .init(title: "flatMapLatest", description: "操作符 flatMapLatest", action: flatMapLatestRx),
    .init(title: "withLatestFrom", description: "操作符 withLatestFrom", action: withLatestFromRx),
    .init(title: "Button", description: "模拟按钮点击", action: buttonTapped ),
    .init(title: "防抖", description: "操作符 debounce", action: debounceTest),
    .init(title: "节气门", description: "操作符 throttle", action: throttleTest),
    .init(title: "网络请求", description: "flatMapFirst", action: networkTest),
    .init(title: "网络轮询", description: "interval", action: runloop),
    
  ]
}

private let button = PublishSubject<Int>()
private var count = 1
private func buttonTapped() {
  button.onNext(count)
  count += 1
}


/// 延时事件，相对时间内只有一个事件
private func debounceTest() {
  _ = button.asObservable()
    .debug()
    .debounce(.milliseconds(600), scheduler: MainScheduler.instance)
    .debug()
    .subscribe()
}

/// 节气门事件，相对时间内只有一个事件
private func throttleTest() {
  _ = button.asObservable()
    .debug()
    .throttle(.milliseconds(600), latest: false, scheduler: MainScheduler.instance)
    .debug()
    .subscribe()
}

private func networkTest() {
  _ = button.asObservable()
    .flatMap { count in
      return networkMockError(count)
        .map { _ in () }
        .catchAndReturn(())
        .debug()
    }
    .debug()
    .subscribe(onNext: { number in
      Timber.d(#function, number)
    }, onError: {
      Timber.d(#function, $0)
    }, onDisposed:  {
      Timber.d(#function)
    })
}

enum NetworkError: Error {
  case loginFailed
}

func networkMock(_ number: Int) -> Single<Int> {
  return .just(number)
}

func networkMockError(_ number: Int) -> Single<Int> {
  return Single.error(NetworkError.loginFailed)
}
